package gipfProject.games.zertz.data;

import java.util.Iterator;

public class IsolationRules{
	
	private RuleData rules;
	
	
	ZertzData gameState;

	/**
	 *  -2 = Not a valid tile
	 *  -1 = Unchecked
	 *   0 = Not Isolated
	 *   1 = Isolated
	 *   2 = Still checking
	 */

	static enum hasLife {Invalid,Safe,Remove};
	hasLife[][] isoBoard;
	
	static final int
		INVALID = -1,
		SAFE = 0,
		REMOVE = 1;

	public IsolationRules(RuleData rules, ZertzData gameState){
		this.rules = rules;
		this.gameState = gameState;
	}
	
	/**
	 * This checks for islands of pieces that have no empty spaces
	 * It then has the current player capture all of those islands
	 * 
	 * This also removes the rings, unlike a normal capture
	 */
	public void runLife(){
		initializeLife();
		spreadLife();
		captureDead();
	}
	
	private void initializeLife(){
		//Create the board
		isoBoard = new hasLife[ZertzData.boardCols][ZertzData.boardRows];
		
		//For each spot on the board
		for (int x = 0; x < ZertzData.boardCols ; x++){
			for (int y = 0; y < ZertzData.boardRows ; y++){
				//Mark invalid pieces
				if (!gameState.getPiece(x,y).isValid()){
					isoBoard[x][y] = hasLife.Invalid;
				}
				//Mark empty pieces as safe
				else if (gameState.getPiece(x,y).isEmpty()){
					isoBoard[x][y] = hasLife.Safe;
				}
				//All other pieces are initially marked for removal
				else{
					isoBoard[x][y] = hasLife.Remove;
				}
			}
		}		
	}
	
	private void spreadLife(){
		//For each spot on the board
		for (int x = 0; x < ZertzData.boardCols ; x++){
			for (int y = 0; y < ZertzData.boardRows ; y++){
				//Spread the safety of that piece to it's neighbors
				spreadPiece(x,y);
			}
		}			
	}
		
	/**
	 * If this piece is safe, spread that safety to all of it's neighbors
	 * 
	 * @param x
	 * @param y
	 */
	private void spreadPiece(int x, int y){
		//Cancel if this piece is not actually safe
		if (isoBoard[x][y] != hasLife.Safe){
			return;
		}
		
		//For each neighboring piece
		Iterator<Location> iterator = gameState.listValidNeighbors(new Location(x,y)).iterator();
		while (iterator.hasNext())
		{
			Location testLocation = iterator.next();
			
			//Set that neighbor to be SAFE as well
			setSafe(testLocation.x,testLocation.y);
		}
	}
	
	/**
	 * Sets a piece that was formerly marked for REMOVE as SAFE,
	 * and spreads this to all of it's neighboring pieces
	 * 
	 * Has no effect on non-REMOVE pieces, to prevent recursion
	 * 
	 * @param x
	 * @param y
	 */
	private void setSafe(int x, int y){
		//We can skip this if the piece isn't marked for removal (this prevents recursion)
		if (isoBoard[x][y] != hasLife.Remove ){
			return;
		}
		
		//Mark the piece as safe
		isoBoard[x][y] = hasLife.Safe;
		
		//And spread that new-found safety to all of it's neighbors
		spreadPiece(x,y);
	}
	
	private void captureDead(){
		//For each spot on the board
		for (int x = 0; x < ZertzData.boardCols ; x++){
			for (int y = 0; y < ZertzData.boardRows ; y++){
				//If the piece isn't found to be safe, remove it!
				if (isoBoard[x][y] == hasLife.Remove ){
					gameState.isolationCapture(x,y);
				}
			}
		}			
	}

}//End class Isolation()